package wechat

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

type AccessTokenResponse struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
	ErrCode     int    `json:"errcode"`
	ErrMsg      string `json:"errmsg"`
}

// 获取微信小程序的接口调用凭证
// 文档地址： https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html
func GetMiniAppAccessToken(appID, appSecret string) (string, error) {
	// 请求地址： GET https://api.weixin.qq.com/cgi-bin/token
	// 请求参数：
	// grant_type: 获取access_token填写client_credential
	// appid: 小程序唯一标识
	// secret: 小程序的app secret
	// 返回参数：
	// access_token: 获取到的凭证
	// expires_in: 凭证有效时间，单位：秒

	// 实现HTTP请求并解析响应
	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appID, appSecret)
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	var result AccessTokenResponse
	if err := json.Unmarshal(body, &result); err != nil {
		return "", err
	}

	if result.AccessToken == "" {
		return "", fmt.Errorf("get access_token failed: %s", result.ErrMsg)
	}
	return result.AccessToken, nil

}

type PhoneNumberResponse struct {
	ErrCode   int    `json:"errcode"`
	ErrMsg    string `json:"errmsg"`
	PhoneInfo struct {
		PhoneNumber     string `json:"phoneNumber"`
		PurePhoneNumber string `json:"purePhoneNumber"`
		CountryCode     string `json:"countryCode"`
		Watermark       struct {
			Timestamp int    `json:"timestamp"`
			AppID     string `json:"appid"`
		} `json:"watermark"`
	} `json:"phone_info"`
}

// 获取手机号
// 文档地址： https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
func GetMiniAppPhoneNumber(accessToken, code string) (string, error) {
	// 请求地址： POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN
	// 请求参数：
	// code: 通过 wx.login 接口获取的 code
	// 返回参数：
	// phone_info: 用户手机号信息
	// 实现HTTP请求并解析响应
	url := fmt.Sprintf("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s", accessToken)
	payload := map[string]string{"code": code}
	payloadBytes, err := json.Marshal(payload)
	if err != nil {
		return "", err
	}

	resp, err := http.Post(url, "application/json", bytes.NewBuffer(payloadBytes))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	var result PhoneNumberResponse
	if err := json.Unmarshal(body, &result); err != nil {
		return "", err
	}

	if result.ErrCode != 0 {
		return "", fmt.Errorf("get phone number failed: %s", result.ErrMsg)
	}
	return result.PhoneInfo.PhoneNumber, nil
}

// 调用微信接口获取 access_token,然后通过 access_token+code 获取手机号
// 综合以上两个接口
func GetPhoneNumber(appID, appSecret, code string) (string, error) {
	accessToken, err := GetMiniAppAccessToken(appID, appSecret)
	if err != nil {
		return "", err
	}
	phoneNumber, err := GetMiniAppPhoneNumber(accessToken, code)
	if err != nil {
		return "", err
	}
	return phoneNumber, nil
}
